home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / CUJ9208.ARJ / CMENU14.EXE / RMENU1.C < prev    next >
C/C++ Source or Header  |  1992-06-19  |  9KB  |  397 lines

  1. /************************************************************
  2.  *    Program: RMENU Menu Interpreter
  3.  *  Module: rmenu1.c
  4.  *        Main and Utility Functions
  5.  *    Written by: Leor Zolman, 7/91
  6.  ************************************************************/
  7.  
  8. #include "cmenu.h"
  9. #include "rcmenu.h"
  10.  
  11. #if __STDC__
  12. #    pragma hdrstop
  13. #    include <stdarg.h>
  14. #else
  15. #    include <varargs.h>
  16. #endif
  17.  
  18. #include <ctype.h>
  19.  
  20. /********************** Global Data *************************/
  21.  
  22. LEVELS LMenus[MAX_NEST];
  23. int    nestlev;                /* current nesting level        */
  24. int    echox, echoy;            /* Location of item # echo area */
  25. int    debug;                    /* true to display sys commands    */
  26. char SysShell[80];            /* System command interpreter    */
  27. char sav_cmd[];                /* Saved system command            */
  28.  
  29. /************************************************************
  30.  * main():
  31.  *    Initialize the program and run
  32.  *    the master menu
  33.  ************************************************************/
  34.  
  35. main(argc, argv)
  36. int argc;
  37. char **argv;
  38. {
  39.     char *mname = "menu";
  40.     int i, j, aftersemi;
  41.     char sav_cmd2[200], *cp, *cp2;
  42.  
  43.     debug = 0;                    /* No debugging by default        */
  44.     *sav_cmd = '\0';            /* No saved system command yet    */
  45.                                 /* Process command line options: */
  46.     for (i = 1; i < argc; i++)
  47.         if (argv[i][0] == '-')
  48.         {
  49.             switch (tolower(argv[i][1]))
  50.             {
  51.                 case 'd':    debug = TRUE;
  52.                             break;
  53.  
  54.                 default:    fprintf(stderr, "Unknown option: '%s'\n",
  55.                                         argv[i]);
  56.                             exit(0);
  57.             }
  58.             for (j = i; j < argc - 1; j++)    /* compress */
  59.                 argv[j] = argv[j + 1];        /* arg list */
  60.             argc--;
  61.             i--;
  62.         }
  63.  
  64.     init_win();        /* initialize curses */
  65.  
  66.     if (argc == 2)
  67.         mname = argv[1];
  68.  
  69.     nestlev = 0;
  70.     do_menu("", mname);
  71.     free_menus();
  72.     close_win();
  73.                     /* If user pressed "x" while viewing an    */
  74.     if (*sav_cmd)    /* action command, show it upon exit:    */
  75.     {
  76.         for (cp = sav_cmd, cp2 = sav_cmd2; *cp; cp++)
  77.         {
  78.             if (*cp == ';')
  79.             {
  80.                 *cp2++ = '\n';
  81.                 *cp2++ = '\t';
  82.                 aftersemi = TRUE;
  83.                 continue;
  84.             }
  85.             else if (aftersemi && isspace(*cp))
  86.                 continue;
  87.             *cp2++ = *cp;
  88.             aftersemi = FALSE;
  89.         }
  90.         *cp2 = '\0';
  91.         printf("The viewed action command was:\n\t%s\n", sav_cmd2);
  92.     }
  93.     
  94.     return OK;
  95. }
  96.  
  97.  
  98. /************************************************************
  99.  * do_menu(): 
  100.  *    Run a compiled menu file, supporting recursive
  101.  *    calls for nested external menus.
  102.  *    Default command/menu path is supplied as "path".
  103.  ************************************************************/
  104.  
  105. int do_menu(path, file)
  106. char *path, *file;
  107. {
  108.     char pathname[MAX_PATH];
  109.     
  110.     strcpy(pathname, path);
  111.     if (*path) 
  112.         strcat(pathname, "/");
  113.     strcat(pathname, file);
  114.     strcat(pathname, ".mnc");
  115.  
  116.     if (ld_menu(pathname) == ERROR)
  117.         return EXITALL;
  118.  
  119.     return sub_menu(0, path);    /* run main menu in file */ 
  120. }
  121.  
  122.         
  123. /************************************************************
  124.  * ld_menu():
  125.  *    Load a compiled menu object file from disk,
  126.  *    into nesting level nestlev, allocating memory
  127.  *    as required.
  128.  *    For each menu in the menu file being loaded,
  129.  *    compute screen placement as per spacing/columns
  130.  *    specifications and the total number of items.
  131.  ************************************************************/
  132.  
  133. int ld_menu(path)
  134. char *path;
  135. {
  136.     LEVELS *Levp = &LMenus[nestlev];
  137.     MENU *Mp;
  138.     ITEM *Ip;
  139.     MENU2 *M2p;
  140.  
  141.     FILE *fp;
  142.     int widest;
  143.     int i, j, k, l;
  144.     
  145.     if ((fp = fopen(path, "rb")) == NULL)
  146.         return fatal("Can't open %s", path);
  147.     
  148.     if (fread((Void *) &Levp->n_menus, sizeof (int), 1, fp)
  149.                     != 1)
  150.         return fatal("Error reading menu count from %s", path);
  151.     
  152.     for (i = 0; i < Levp->n_menus; i++)
  153.     {
  154.         if (i < Levp -> max_menus)
  155.             M2p = Levp -> Menus[i];
  156.         else                        /* allocate memory for Menu    */
  157.         {
  158.             M2p = Levp -> Menus[i] = (MENU2 *) malloc(sizeof(MENU2));
  159.             if (M2p == NULL)
  160.                 return fatal("Out of memory loading %s", path);
  161.             Levp -> max_menus++;
  162.             M2p -> most_items = 0;
  163.         }
  164.  
  165.         Mp = &M2p -> Menu;
  166.         
  167.         if (fread((Void *) Mp, sizeof(MENU), 1, fp) != 1)
  168.             return fatal("Error reading Menu data from %s", path);
  169.         
  170.     /* Now determine screen placement strategy. */
  171.  
  172.         placement(Mp);
  173.  
  174.         M2p -> field_len = min(MAX_TXTWID, 
  175.                     (SCREEN_COLS / Mp -> columns) - 5);
  176.  
  177.     /* Read in each item, and assign screen coordinate info */
  178.     /* to each on-the-fly as per spacing/column parameters    */
  179.         
  180.         for (j = 0; j < Mp -> nitems; j++)
  181.         {
  182.             if (j < M2p -> most_items)
  183.                 Ip = M2p -> Items[j];
  184.             else
  185.             {
  186.                 Ip = M2p -> Items[j] = (ITEM *) malloc(sizeof(ITEM));
  187.                 if (Ip == NULL)
  188.                    return fatal("Out of memory loading %s, menu #%d/item #%d",
  189.                         path, i,j);
  190.                 M2p -> most_items++;
  191.             }
  192.             if (fread((Void *) Ip, sizeof(ITEM), 1, fp) != 1)
  193.                 return fatal("Error reading %s", path);
  194.  
  195.             Ip -> text[M2p -> field_len - 1] = '\0'; /* truncate */
  196.  
  197.             if ((Ip -> acttyp == ACT_LMENU ||
  198.                  Ip -> acttyp == ACT_EMENU) &&
  199.                 strlen(Ip -> text) + 6 < M2p -> field_len)
  200.             {
  201.                 int limit;
  202.                 
  203.                 limit = min (Mp -> widest + 2,
  204.                         M2p -> field_len - 7);
  205.                 for (k = strlen(Ip -> text);
  206.                         k < limit && k < (MAX_TXTWID - 6); k++)
  207.                     strcat(Ip -> text, " ");
  208.                 strcat(Ip -> text, "(MENU)");
  209.             }
  210.  
  211.             M2p -> coords[j].ypos = 
  212.                     HOME_Y + (j % (MAX_IROWS / Mp -> spacing))
  213.                                 * Mp -> spacing;
  214.  
  215.             widest = Mp -> widest;
  216.             M2p -> coords[j].xpos = HOME_X + 
  217.                     (
  218.                       (Mp -> columns == 1)
  219.                               ? 
  220.                       (
  221.                           (SCREEN_COLS - HOME_X -
  222.                          (widest + ((widest < 66) ? 14 : 6) )) / 2
  223.                       )
  224.                             :
  225.                       (j / (MAX_IROWS / Mp -> spacing) *
  226.                            (SCREEN_COLS / Mp -> columns))
  227.                     );
  228.  
  229.  
  230.             M2p -> coords[j].spaces_needed = 
  231.                     min(M2p -> field_len, Mp -> widest)
  232.                             - strlen(Ip -> text);
  233.         }
  234.     }
  235.     fclose(fp);
  236.     return OK;
  237. }
  238.  
  239.  
  240. /************************************************************
  241.  * placement():
  242.  *    Calculate values for columns and spacing 
  243.  *    for the given Menu:
  244.  ************************************************************/
  245.  
  246. Void placement(Mp)
  247. MENU *Mp;
  248. {
  249.     int columns = Mp -> columns;
  250.     int spacing = Mp -> spacing;
  251.     int nitems = Mp -> nitems;
  252.  
  253.     /* Step 1: fill in real values if either    */
  254.     /*    columns or spacing was not specified:    */
  255.  
  256.     if (spacing == DEFAULT && columns == DEFAULT)
  257.     {
  258.         if (nitems <= (MAX_IROWS / 2))
  259.         {
  260.             Mp -> columns = 1;
  261.             Mp -> spacing = 2;
  262.         }
  263.         else if (nitems <= MAX_IROWS)
  264.             if ((Mp -> widest * 2 + 5) <= SCREEN_COLS)
  265.                 Mp -> columns = Mp -> spacing = 2;
  266.             else
  267.                 Mp -> columns = Mp -> spacing = 1;
  268.         else
  269.         {
  270.             Mp -> spacing = 1;
  271.             Mp -> columns = (nitems - 1) / MAX_IROWS + 1;
  272.         }
  273.     }
  274.     else if (spacing == DEFAULT)
  275.         Mp -> spacing =
  276.                 (nitems <= (MAX_IROWS / 2)) ? 2 : 1;
  277.     else if (columns == DEFAULT)
  278.         if (Mp -> spacing == 1)
  279.             Mp -> columns = (nitems - 1) / MAX_IROWS + 1;
  280.         else
  281.             Mp -> columns = (nitems - 1) / (MAX_IROWS / 2) + 1;
  282.         
  283.     /* Step 2: Adjust if out of range: */
  284.             
  285.     while (MAX_IROWS / Mp -> spacing * Mp -> columns < nitems)
  286.         if (Mp -> spacing != 1)
  287.             Mp -> spacing = 1;
  288.         else
  289.             Mp -> columns++;
  290.     return;
  291. }
  292.  
  293.  
  294. /************************************************************
  295.  * free_menus():
  296.  *    Free up memory allocated for ALL menu items:
  297.  ************************************************************/
  298.  
  299. Void free_menus()
  300. {
  301.     int i, j, k;
  302.     MENU2 *m2p;
  303.     
  304.     for (i = 0; i < MAX_NEST; i++)
  305.         for (j = 0; j < LMenus[i].max_menus; j++)
  306.         {
  307.             m2p = LMenus[i].Menus[j];
  308.             for (k = 0; k < m2p -> most_items; k++)
  309.                 free(m2p -> Items[k]);
  310.             free(m2p);
  311.         }
  312. }
  313.  
  314.  
  315. /************************************************************
  316.  * fatal(): Complain and exit.
  317.  ************************************************************/
  318.  
  319. #if __STDC__                 /* use ANSI variable-#-of-args method    */
  320.  
  321. int fatal (char *fmt, ...)
  322. {
  323.     char ftext[200], ffmt[55];
  324.     va_list arglist;
  325.     
  326.     va_start(arglist, fmt);
  327.  
  328. #else                        /* or old varargs method:                */
  329.  
  330. int fatal(fmt, va_alist)
  331. char *fmt;
  332. va_dcl
  333. {
  334.     char ftext[200], ffmt[55];
  335.     va_list arglist;
  336.     
  337.     va_start(arglist);
  338. #endif
  339.  
  340.     vsprintf(ffmt, fmt, arglist);
  341.     sprintf(ftext, "Fatal error in rmenu: %s", ffmt);
  342.  
  343.     put_msg(1, ftext);
  344.  
  345.     va_end(arglist);
  346.     return ERROR;
  347. }
  348.  
  349.  
  350. /************************************************************
  351.  * put_msg(): Display a message on the menu screen
  352.  *    Return the character typed to continue
  353.  ************************************************************/
  354.  
  355. #if __STDC__
  356. int put_msg (int bell, char *fmt, ...)
  357. {
  358.     char ftext[200];
  359.     va_list arglist;
  360.     char c;
  361.     
  362.     va_start(arglist, fmt);
  363.     
  364. #else
  365. int put_msg(bell, fmt, va_alist)
  366. int bell;
  367. char *fmt;
  368. va_dcl
  369. {
  370.     char ftext[200];
  371.     va_list arglist;
  372.     char c;
  373.     
  374.     va_start(arglist);
  375. #endif
  376.     
  377.     move(ERR_ROW, 0);
  378.     hlight_on();
  379.  
  380.     if (bell)
  381.         beep();
  382.  
  383. /*    vwprintw(stdscr, fmt, arglist); */
  384.     vsprintf(ftext, fmt, arglist);
  385.     addstr(ftext);
  386.     va_end(arglist);
  387.     refresh();
  388.  
  389.     c = getch();
  390.  
  391.     move (ERR_ROW, 0);
  392.     hlight_end();
  393.     clrtoeol();
  394.     refresh();
  395.     return c;
  396. }
  397.